@namespace Oqtane.Modules.Admin.Modules
@using Oqtane.Interfaces
@inherits ModuleBase
@inject NavigationManager NavigationManager
@inject IThemeService ThemeService
@inject IModuleService ModuleService
@inject IPageModuleService PageModuleService
@inject IStringLocalizer<Settings> Localizer
@inject IStringLocalizer<SharedResources> SharedLocalizer

<form @ref="form" class="@(validated ? "was-validated" : "needs-validation")" novalidate>
    <TabStrip>
        <TabPanel Name="Settings" Heading="Settings" ResourceKey="Settings">
            @if (_containers != null)
            {
                <div class="container">
                    <div class="row mb-1 align-items-center">
                        <Label Class="col-sm-3" For="module" HelpText="The name of the module" ResourceKey="Module">Module: </Label>
                        <div class="col-sm-9">
                            <input id="module" type="text" class="form-control" @bind="@_module" disabled />
                        </div>
                    </div>
                    <div class="row mb-1 align-items-center">
                        <Label Class="col-sm-3" For="title" HelpText="Enter the title of the module" ResourceKey="Title">Title: </Label>
                        <div class="col-sm-9">
                            <input id="title" type="text" class="form-control" @bind="@_title" required />
                        </div>
                    </div>
                    <div class="row mb-1 align-items-center">
                        <Label Class="col-sm-3" For="pane" HelpText="The pane where the module will be displayed" ResourceKey="Pane">Pane: </Label>
                        <div class="col-sm-9">
                            <select class="form-select" @bind="@_pane">
                                @foreach (string pane in PageState.Page.Panes)
                                {
                                    <option value="@pane">@pane Pane</option>
                                }
                            </select>
                        </div>
                    </div>
                    <div class="row mb-1 align-items-center">
                        <Label Class="col-sm-3" For="container" HelpText="Select the module's container" ResourceKey="Container">Container: </Label>
                        <div class="col-sm-9">
                            <select id="container" class="form-select" @bind="@_containerType" required>
                                @foreach (var container in _containers)
                                {
                                    <option value="@container.TypeName">@container.Name</option>
                                }
                            </select>
                        </div>
                    </div>
                    <div class="row mb-1 align-items-center">
                        <Label Class="col-sm-3" For="allpages" HelpText="Indicate if this module should be displayed on all pages" ResourceKey="DisplayOnAllPages">Display On All Pages? </Label>
                        <div class="col-sm-9">
                            <select id="allpages" class="form-select" @bind="@_allPages" required>
                                <option value="True">@SharedLocalizer["Yes"]</option>
                                <option value="False">@SharedLocalizer["No"]</option>
                            </select>
                        </div>
                    </div>
                    <div class="row mb-1 align-items-center">
                        <Label Class="col-sm-3" For="page" HelpText="The page that the module is located on" ResourceKey="Page">Page: </Label>
                        <div class="col-sm-9">
                            <select id="page" class="form-select" @bind="@_pageId" required>
                                @if (PageState.Page.UserId != null)
                                {
                                    <option value="@PageState.Page.PageId">@(PageState.Page.Name)</option>
                                }
                                else
                                {
                                    foreach (Page p in PageState.Pages)
                                    {
                                        if (UserSecurity.IsAuthorized(PageState.User, PermissionNames.Edit, p.PermissionList))
                                        {
                                            <option value="@p.PageId">@(new string('-', p.Level * 2))@(p.Name)</option>
                                        }
                                    }

                                }
                            </select>
                        </div>
                    </div>
                </div>
            }
        </TabPanel>
        <TabPanel Name="Permissions" ResourceKey="Permissions">
            @if (_permissions != null)
            {
                <div class="container">
                    <div class="row mb-1 align-items-center">
                        <PermissionGrid EntityName="@EntityNames.Module" PermissionNames="@_permissionNames" PermissionList="@_permissions" @ref="_permissionGrid" />
                    </div>
                </div>

            }
        </TabPanel>
        @if (_moduleSettingsType != null)
        {
            <TabPanel Name="ModuleSettings" Heading="@_moduleSettingsTitle" ResourceKey="ModuleSettings">
                @ModuleSettingsComponent
            </TabPanel>
        }
        @if (_containerSettingsType != null)
        {
            <TabPanel Name="ContainerSettings" Heading="Container Settings" ResourceKey="ContainerSettings">
                @ContainerSettingsComponent
            </TabPanel>
        }
    </TabStrip>
    <br />
    <button type="button" class="btn btn-success" @onclick="SaveModule">@SharedLocalizer["Save"]</button>
    <NavLink class="btn btn-secondary" href="@NavigateUrl()">@SharedLocalizer["Cancel"]</NavLink>
    <br />
    <br />
    <AuditInfo CreatedBy="@createdby" CreatedOn="@createdon" ModifiedBy="@modifiedby" ModifiedOn="@modifiedon"></AuditInfo>
</form>

@code {
    public override SecurityAccessLevel SecurityAccessLevel => SecurityAccessLevel.Edit;
    public override string Title => "Module Settings";

    private ElementReference form;
    private bool validated = false;
    private List<ThemeControl> _containers = new List<ThemeControl>();
    private string _module;
    private string _title;
    private string _pane;
    private string _containerType;
    private string _allPages = "false";
    private string _permissionNames = "";
    private List<Permission> _permissions = null;
    private string _pageId;
    private PermissionGrid _permissionGrid;
    private Type _moduleSettingsType;
    private object _moduleSettings;
    private string _moduleSettingsTitle = "Module Settings";
    private RenderFragment ModuleSettingsComponent { get; set; }
    private Type _containerSettingsType;
    private object _containerSettings;
    private RenderFragment ContainerSettingsComponent { get; set; }
    private string createdby;
    private DateTime createdon;
    private string modifiedby;
    private DateTime modifiedon;

    protected override void OnInitialized()
    {
        _module = ModuleState.ModuleDefinition.Name;
        _title = ModuleState.Title;
        _pane = ModuleState.Pane;
        _containers = ThemeService.GetContainerControls(PageState.Site.Themes, PageState.Page.ThemeType);
        _containerType = ModuleState.ContainerType;
        _allPages = ModuleState.AllPages.ToString();
        _permissions = ModuleState.PermissionList;
        _pageId = ModuleState.PageId.ToString();
        createdby = ModuleState.CreatedBy;
        createdon = ModuleState.CreatedOn;
        modifiedby = ModuleState.ModifiedBy;
        modifiedon = ModuleState.ModifiedOn;

        if (ModuleState.ModuleDefinition != null)
        {
            _permissionNames = ModuleState.ModuleDefinition?.PermissionNames;

            if (!string.IsNullOrEmpty(ModuleState.ModuleDefinition.SettingsType))
            {
                // module settings type explicitly declared in IModule interface
                _moduleSettingsType = Type.GetType(ModuleState.ModuleDefinition.SettingsType);
            }
            else
            {
                // legacy support - module settings type determined by convention ( ie. existence of a "Settings.razor" component in module )
                _moduleSettingsType = Type.GetType(ModuleState.ModuleDefinition.ControlTypeTemplate.Replace(Constants.ActionToken, PageState.Action), false, true);
            }
            if (_moduleSettingsType != null)
            {
                var moduleobject = Activator.CreateInstance(_moduleSettingsType) as IModuleControl;
                if (!string.IsNullOrEmpty(moduleobject.Title))
                {
                    _moduleSettingsTitle = moduleobject.Title;
                }

                ModuleSettingsComponent = builder =>
                {
                    builder.OpenComponent(0, _moduleSettingsType);
                    builder.AddComponentReferenceCapture(1, inst => { _moduleSettings = Convert.ChangeType(inst, _moduleSettingsType); });
                    builder.CloseComponent();
                };
            }
        }
        else
        {
            AddModuleMessage(string.Format(Localizer["Error.Module.Load"], ModuleState.ModuleDefinitionName), MessageType.Error);
        }

        var theme = PageState.Site.Themes.FirstOrDefault(item => item.Containers.Any(themecontrol => themecontrol.TypeName.Equals(_containerType)));
        if (theme != null && !string.IsNullOrEmpty(theme.ContainerSettingsType))
        {
            _containerSettingsType = Type.GetType(theme.ContainerSettingsType);
            if (_containerSettingsType != null)
            {
                ContainerSettingsComponent = builder =>
                {
                    builder.OpenComponent(0, _containerSettingsType);
                    builder.AddComponentReferenceCapture(1, inst => { _containerSettings = Convert.ChangeType(inst, _containerSettingsType); });
                    builder.CloseComponent();
                };
            }
        }
    }

    private async Task SaveModule()
    {
        validated = true;
        var interop = new Interop(JSRuntime);
        if (await interop.FormValid(form))
        {
            if (!string.IsNullOrEmpty(_title))
            {
                var pagemodule = await PageModuleService.GetPageModuleAsync(ModuleState.PageModuleId);
                pagemodule.PageId = int.Parse(_pageId);
                pagemodule.Title = _title;
                pagemodule.Pane = _pane;
                pagemodule.ContainerType = (_containerType != "-") ? _containerType : string.Empty;
                if (!string.IsNullOrEmpty(pagemodule.ContainerType) && pagemodule.ContainerType == PageState.Page.DefaultContainerType)
				{
					pagemodule.ContainerType = string.Empty;
				}
				if (!string.IsNullOrEmpty(pagemodule.ContainerType) && pagemodule.ContainerType == PageState.Site.DefaultContainerType)
				{
					pagemodule.ContainerType = string.Empty;
				}
				await PageModuleService.UpdatePageModuleAsync(pagemodule);
				await PageModuleService.UpdatePageModuleOrderAsync(pagemodule.PageId, pagemodule.Pane);

				var module = ModuleState;
				module.AllPages = bool.Parse(_allPages);
				module.PageModuleId = ModuleState.PageModuleId;
				module.PermissionList = _permissionGrid.GetPermissionList();
				await ModuleService.UpdateModuleAsync(module);

                if (_moduleSettingsType != null)
                {
                    if (_moduleSettings is ISettingsControl moduleSettingsControl)
                    {
                        // module settings updated using explicit interface
                        await moduleSettingsControl.UpdateSettings();
                    }
                    else
                    {
                        // legacy support - module settings updated by convention ( ie. by calling a public method named "UpdateSettings" in settings component )
                        _moduleSettings?.GetType().GetMethod("UpdateSettings")?.Invoke(_moduleSettings, null);
                    }
                }

                if (_containerSettingsType != null && _containerSettings is ISettingsControl containerSettingsControl)
                {
                    await containerSettingsControl.UpdateSettings();
                }

                NavigationManager.NavigateTo(NavigateUrl());
            }
            else
            {
                AddModuleMessage(Localizer["Message.Required.Title"], MessageType.Warning);
            }
        }
        else
        {
            AddModuleMessage(SharedLocalizer["Message.InfoRequired"], MessageType.Warning);
        }
    }

}
